//
// 嗨~ o(*￣▽￣*)ブ
// Created by Mokou on 2020/7/17.
//

#import <AVFoundation/AVFoundation.h>
#import <CoreMedia/CoreMedia.h>
#import "ElecMaterial.h"
#import "Util.h"
#import "GlobalData.h"

@implementation ElecMaterial

- (instancetype)init:(NSDictionary *)_data {
    if (self = super.init) {
        self.id = @"";
        if ([Util notNull:_data k:@"id"])
            self.id = _data[@"id"];

        NSArray *typeArr = @[@(type_db_material_text), @(type_db_material_photo), @(type_db_material_video)];
        if ([Util notNull:_data k:@"type"])
            self.type = [_data[@"type"] intValue];
        if (![typeArr containsObject:@(self.type)])
            self.type = type_db_material_text;

        self.name = @"";
        if ([Util notNull:_data k:@"name"])
            self.name = _data[@"name"];

        self.content = @"";
        if ([Util notNull:_data k:@"content"])
            self.content = _data[@"content"];

        self.md5 = @"";
        if ([Util notNull:_data k:@"md5"]) {
            NSString *md5 = _data[@"md5"];
            self.md5 = md5;
        }

        self.size = 0L;
        if ([Util notNull:_data k:@"size"])
            self.size = [_data[@"size"] longLongValue];

        self.createtime = 0L;
        if ([Util notNull:_data k:@"createtime"])
            self.createtime = [_data[@"createtime"] longLongValue];

        self.duration = 0L;
        if ([Util notNull:_data k:@"duration"])
            self.duration = [_data[@"duration"] longLongValue];
    }
    return self;
}

- (NSDictionary *)getDict {
    return @{
            @"id": self.id,
            @"type": @(self.type),
            @"name": self.name,
            @"content": self.content,
            @"md5": self.md5,
            @"size": @(self.size),
            @"createtime": @(self.createtime),
            @"duration": @(self.duration),
    };
}

- (BOOL)typeHasFile {
    NSArray *typeArr = @[@(type_db_material_photo), @(type_db_material_video)];
    return [typeArr containsObject:@(self.type)];
}

+ (NSDictionary *)insert:(NSDictionary *)_data {
    NSDictionary *callBackRes = @{};

    if (![Util notNull:_data k:@"data"]) return callBackRes;
    NSDictionary *data = _data[@"data"];
    if (![Util notNull:data k:@"s_id"] || ![Util notNull:data k:@"material"]) return callBackRes;

    Database *db = [GlobalData shareInstance].db;

    NSString *s_id = data[@"s_id"];
    NSDictionary *material_data = data[@"material"];
    ElecMaterial *material = [[ElecMaterial alloc] init:material_data];
    material.createtime = [Util now];

    if(material.typeHasFile) {
        // 获取已经保存好的文件信息
        NSArray *tmpMedia = [db tempMedia_select:material.content];
        if (tmpMedia.count > 0) {
            material.content = tmpMedia[0][@"content"];
            material.absolutePath = tmpMedia[0][@"absolute_path"];
            material.md5 = tmpMedia[0][@"md5"];
        }
    }

    // 若类型为视频, 则读取视频时长
    if (material.type == type_db_material_video){
        AVURLAsset *avUrl = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:material.absolutePath]];
        CMTime time = [avUrl duration];
        float second = time.value/(time.timescale ?: 1);
        material.duration = (long long int) (second * 1000);
    }
    // 若类型为文本, 则计算size
    if (material.type == type_db_material_text) {
        material.size = (long long int) [material.content dataUsingEncoding:NSUTF8StringEncoding].length;
    }

    // 保存素材信息
    NSMutableDictionary *res = [[db material_insert:material] mutableCopy];
    // 向指定的计划插入素材末尾
    NSArray *relationArr = [db relation_select_by_s_id:s_id];
    relationArr = [relationArr sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *a, NSDictionary *b) {
        int order_a = [a[@"playorder"] intValue];
        int order_b = [b[@"playorder"] intValue];
        if (order_a != order_b)
            return (NSComparisonResult) (order_a < order_b);
        else
            return NSOrderedSame;
    }];
    ElecRelation *relation = ElecRelation.new;
    relation.m_id = res[@"id"];
    relation.s_id = s_id;
    if (!relationArr.count) {
        relation.playerorder = 0;
    } else {
        relation.playerorder = [relationArr.lastObject[@"playorder"] intValue] + 1;
    }

    [db relation_insert:relation];

    res[@"playOrder"] = @(relation.playerorder);

    NSArray *scheduleArr = [db schedule_select:s_id];
    if (scheduleArr.count) {
        ElecSchedule *schedule = [[ElecSchedule alloc] init:scheduleArr[0]];

        // 修改计划素材总体积
        schedule.size += material.size;

        // 修改计划总播放时间
        switch (material.type) {
            case type_db_material_text: {
                break;
            }
            case type_db_material_photo: {
                schedule.duration += schedule.material_duration;
                break;
            }
            case type_db_material_video: {
                schedule.duration += material.duration;
                break;
            }
            default:{}
        }

        [db schedule_update:schedule];
    }

    // 修改计划更新时间
    [ElecSchedule refreshUpdateTime:s_id];

    if (material.typeHasFile) {
        //若为非文本类型, 则将当前的文件绝对路径反馈给flutter
        res[@"content"] = material.absolutePath;
    }

    callBackRes = [Util callBackJson:@{@"material": res}];

    return callBackRes;
}

+ (void)delete:(NSDictionary *)_data {
    if (![Util notNull:_data k:@"data"]) return;
    NSDictionary *data = _data[@"data"];
    if (![Util notNull:data k:@"id"] || ![Util notNull:data k:@"s_id"]) return;

    NSString *m_id = data[@"id"];
    NSString *s_id = data[@"s_id"];

    Database *db = [GlobalData shareInstance].db;

    NSArray *scheduleArr = [db schedule_select:s_id];
    NSArray *materialArr = [db material_select:m_id];
    if (scheduleArr.count && materialArr.count) {
        ElecSchedule *schedule = [[ElecSchedule alloc] init:scheduleArr[0]];
        ElecMaterial *material = [[ElecMaterial alloc] init:materialArr[0]];

        // 修改计划素材总体积
        schedule.size -= material.size;

        // 修改计划总时长
        switch (material.type) {
            case type_db_material_text: {
                break;
            }
            case type_db_material_photo: {
                schedule.duration -= schedule.material_duration;
                break;
            }
            case type_db_material_video: {
                schedule.duration -= material.duration;
                break;
            }
            default:{}
        }

        [db schedule_update:schedule];
    }

    //删除指定计划中的指定素材 (关系)
    [db relation_delete_by_s_id_and_m_id:s_id m_id:m_id];

    //判断是否有其他使用该素材文件,没有则删除素材文件
    if (materialArr.count) {
        ElecMaterial *material_for_delete = [[ElecMaterial alloc] init:materialArr[0]];
        if (material_for_delete.typeHasFile) {
            NSArray *material_same_md5 = [db material_select_md5:material_for_delete.md5];
            if (material_same_md5.count <= 1) {
                //删文件
                NSString *absolutePath = [Util getAbsolutePath:material_for_delete.content];
                [[GlobalData shareInstance].fileSelector deleteFile:absolutePath];
            }
            [db material_delete:m_id];
        }
    }
    
    // 修改计划更新时间
    [ElecSchedule refreshUpdateTime:s_id];
}

+ (NSDictionary *)update:(NSDictionary *)_data {
    NSDictionary *callBackRes = @{};

    if (![Util notNull:_data k:@"data"]) return callBackRes;
    NSDictionary *data = _data[@"data"];
    if (![Util notNull:data k:@"material"]) return callBackRes;
    NSDictionary *material_data = data[@"material"];

    ElecMaterial *newMaterial = [[ElecMaterial alloc] init:material_data];
    ElecMaterial *oldMaterial;

    Database *db = [GlobalData shareInstance].db;
    FileSelector *fileSelector = [GlobalData shareInstance].fileSelector;

    NSArray *selectRes = [db material_select:newMaterial.id];
    if (selectRes.count) {
        oldMaterial = [[ElecMaterial alloc] init:selectRes[0]];
    }

    // 新素材类型含有文件 则处理新旧素材文件
    // newMaterial中 的 content 为flutter传入的完整绝对路径
    // oldMaterial中 的 content 为数据库中存储的相对路径
    if (newMaterial.typeHasFile) {
        //按需删除旧素材文件 (参数无md5 || md5与旧素材不一致)
        BOOL deleteOldFile = !newMaterial.md5 || ![newMaterial.md5 isEqualToString:oldMaterial.md5];
        if (deleteOldFile) {
            [fileSelector deleteFile:[Util getAbsolutePath:oldMaterial.content]];
        }

        // 获取已经保存好的文件信息
        NSArray *tmpMedia = [db tempMedia_select:newMaterial.content];
        if (tmpMedia.count > 0) {
            newMaterial.content = tmpMedia[0][@"content"];
            newMaterial.absolutePath = tmpMedia[0][@"absolute_path"];
            newMaterial.md5 = tmpMedia[0][@"md5"];
        }

    }

    //更新指定素材信息
    [db material_update:newMaterial];

    //修改相关计划更新时间
    NSArray *relationArr = [db relation_select_by_m_id:newMaterial.id];
    for (NSDictionary *r in relationArr) {
        if (![Util notNull:r k:@"s_id"]) continue;
        [ElecSchedule refreshUpdateTime:r[@"s_id"]];
    }

    if (newMaterial.typeHasFile) {
        //若为非文本类型, 则将当前的文件绝对路径反馈给flutter
        newMaterial.content = newMaterial.absolutePath;
    }
    callBackRes = [Util callBackJson:@{@"material": newMaterial.getDict}];

    return callBackRes;
}

+ (void)order:(NSDictionary *)_data {
    if (![Util notNull:_data k:@"data"]) return;
    NSDictionary *data = _data[@"data"];
    if (![Util notNull:data k:@"s_id"] || ![Util notNull:data k:@"material"]) return;

    NSString *s_id = data[@"s_id"];
    NSArray *material = data[@"material"];

    Database *db = [GlobalData shareInstance].db;

    // 将参数中的素材顺序写入数据库
    for (int i=0; i< material.count; i++) {
        ElecRelation *r = ElecRelation.new;
        r.s_id = s_id;
        r.m_id = material[i];
        r.playerorder = i;
        [db relation_update_order:r];
    }

    // 修改计划更新时间
    [ElecSchedule refreshUpdateTime:s_id];
}

+ (NSDictionary *)select:(NSDictionary *)_data {
    NSDictionary *callBackRes = @{};

    if (![Util notNull:_data k:@"data"]) return callBackRes;
    NSDictionary *data = _data[@"data"];
    if (![Util notNull:data k:@"s_id"]) return callBackRes;

    NSString *s_id = data[@"s_id"];
    Database *db = [GlobalData shareInstance].db;

    //查询指定计划中的素材
    NSMutableArray *resArr = NSMutableArray.new;
    NSArray *relationArr = [db relation_select_by_s_id:s_id];
    for (NSDictionary *r in relationArr) {
        NSArray *selectRes = [db material_select:r[@"m_id"]];
        if (selectRes.count > 0) {
            NSMutableDictionary *material = [selectRes[0] mutableCopy];
            material[@"playOrder"] = r[@"playorder"];

            ElecMaterial *materialObj = [[ElecMaterial alloc] init:material];
            if (materialObj.typeHasFile) {
                material[@"content"] = [Util getAbsolutePath:materialObj.content];
            }

            [resArr addObject:material];
        }
    }

    resArr = [resArr sortedArrayUsingComparator:^NSComparisonResult(NSDictionary *a, NSDictionary *b) {
        int order_a = [a[@"playOrder"] intValue];
        int order_b = [b[@"playOrder"] intValue];
        if (order_a != order_b)
            return (NSComparisonResult) (order_a > order_b);
        else
            return NSOrderedSame;
    }].mutableCopy;

    callBackRes = [Util callBackJson:resArr];

    return callBackRes;
}

@end
